import { Body, Controller, Get, Post, Req, Response, Headers, OnModuleInit, OnModuleDestroy, Param } from '@nestjs/common';
import { Response as Res } from 'express';
import { request } from 'http';
import axios from 'axios'
import { knext } from 'knext';
import { Knex } from 'knex'

import { InjectEntityManager, InjectMikroORM } from '@mikro-orm/nestjs';
import { EntityManager, MikroORM } from '@mikro-orm/mysql';
import { WechatAppid } from '@databases/entities/WechatAppid';
// import { GeweReceiverService } from './gewe.receiver.controller';
import { LongConnsService } from './long.conns.service';
import { JsonApiResponse } from '@utils/json.api.response';
import { Kafka, Producer, logLevel } from 'kafkajs';
import { RedisService } from './redis.service';
import { StorageService } from './storage.service';
import { QueryService } from './query.service';
//import { SchedulerRegistry } from '@nestjs/schedule';
import { reconize, formMatch, formMatchMultiLine } from '@utils/reconize/index.js'

const gateway = 'http://api.geweapi.com/gewe/v2/api'
const constHeaders = {
    'X-GEWE-TOKEN': 'a20c745e-98da-4586-aad3-113668d5d14a'
}

const gewe = axios.create({
    headers: constHeaders,
    baseURL: gateway
})

@Controller('proxy')
export class ChatController implements OnModuleInit, OnModuleDestroy {

    kafkaHost: string = '134.175.224.228:9092'
    producerGewe: Producer = null

    constructor(
        @InjectMikroORM('zp')
        private readonly orm: MikroORM,
        @InjectEntityManager('zp')
        private readonly em: EntityManager,
        //private schedulerRegistry: SchedulerRegistry
        private longConnService: LongConnsService,
        private redisService: RedisService,
        private storageService: StorageService,
        private queryService: QueryService
    ) { }

    async onModuleInit() {
        // const kafka = new Kafka({
        //     logLevel: logLevel.INFO,
        //     brokers: [`${this.kafkaHost}`],
        //     clientId: 'kafka-receiver',
        // })

        // this.producerGewe = kafka.producer({
        //     allowAutoTopicCreation: true,
        //     transactionTimeout: 30000
        // })

        // await this.producerGewe.connect()
    }

    onModuleDestroy() {
        console.log('GeweReceiverServiceDestroy')
    }

    @Post("info/reconize")
    async reconize(@Body("string") string) {
        if (reconize(string)) {
            let form = formMatchMultiLine(string)

            if(form)
                return JsonApiResponse.object(form,"识别成功")
            else
                return JsonApiResponse.object(null,"识别失败")
        }else{
            return JsonApiResponse.object(null,"识别失败")
        }
    }

    @Post('getWxs')
    async getWxs(@Req() request) {
        let knex = knext(this)

        let wxs = await knex.fromORM(WechatAppid).select('*').where({ owner_id: request.user.id })

        for (const wx of wxs) {
            let target = `${gateway}/login/checkOnline`

            let online = await gewe.post(target, {
                appId: wx.appid,
            })

            wx.status = online.data.data
        }

        return JsonApiResponse.object(wxs)
    }

    @Post('getNewstAfterTime')
    async getNewstAfterTime(
        @Body("Wxid") Wxid,
        @Body("conversationID") conversationID,
        @Body("lastMsgSeq") msgSeq) {
        let res = await this.queryService.getMessageSinceTime(`${Wxid}_${conversationID}`, msgSeq)

        let messages = res[0].newests

        return JsonApiResponse.object(messages)
    }

    @Post('login/checkLogin')
    async checkLogin(
        @Req() request,
        @Body('appId') appId, @Body('uuid') uuid, @Response() resp: Res) {

        let knex = knext(this)

        let target = `${gateway}/login/checkLogin`

        let res = await gewe.post(target, {
            appId,
            uuid
        }, {
            headers: constHeaders,
            responseType: 'json',
        })

        //已经扫码的判断处理
        if (res.status == 200 && res.data.ret == 200) {
            let loginInfo = res.data.data.loginInfo
            let data = res.data.data

            if (res.data.data.status == 2 && loginInfo) {
                await knex.fromORM(WechatAppid).createOrUpdate(
                    ['appid', 'uuid', 'owner_id', 'wxid', 'mobile', 'alias'],
                    {
                        "wxid": loginInfo.wxid,
                        "owner_id": request.user.id,
                    },
                    {
                        "owner_id": request.user.id,
                        "wxid": loginInfo.wxid, //微信号
                        "appid": appId,
                        "uuid": uuid,
                        "uin": loginInfo.uin,
                        "nick_name": data.nickName,
                        "head_img_url": data.headImgUrl,
                        "mobile": loginInfo.mobile,
                        "alias": loginInfo.alias //微信名
                    }
                )

                await this.storageService.setWxid2UserID(loginInfo.wxid, request.user.id)
            }
        }

        resp.set(res.headers)
            .status(res.status)
            .json(res.data)
            .end()
    }

    // @Post('contacts/getBriefInfo')
    // async getConcactInfo(@Body('appId') appId:string,@Body('wxid') wxid: string) {
    //     let contact = await this.redisService.redis().hGet(`CONTACT_INFOS`, wxid);

    //     if (!contact) {
    //         let target = `${gateway}/contacts/getBriefInfo`

    //         let res = await gewe.post(target, {
    //             appId:appId,
    //             wxids:[]
    //         }, {
    //             headers: constHeaders,
    //             responseType: 'json',
    //         })

    //         contact = res.data.data

    //         await this.redisService.redis().hSet(`CONTACT_INFOS`, wxid,contact);
    //     }

    //     return JsonApiResponse.object(contact)
    // }

    @Post('login/getLoginQrCode')
    async getLoginQrCode(@Req() reqeust, @Body() body, @Response() resp: Res) {

        let target = `${gateway}/login/getLoginQrCode`

        try {
            let res = await gewe.post(target, {
                //appId: body.appId,
                regionId: '460000'//body.regionId GUANGDONG 广东
            }, {
                headers: constHeaders,
                responseType: 'json',
            })

            resp.set(res.headers)
                .status(res.status)
                .json(res.data)
                .end()
        } catch (e) {
            return 'FLASE'
        }
    }

    @Get('login/checkLogin')
    async checkLoginGet() {
        let target = `${gateway}/login/checkLogin`
        let res = await gewe.post(target, {
            appId: this.appId,
            uuid: this.uuid
        }, {
            headers: constHeaders,
            responseType: 'json',
        })

        console.log(res)

        return 'OK'
    }

    @Get('login/checkOnline')
    async checkOnline() {
        let target = `${gateway}/login/checkOnline`
        let res = await gewe.post(target, {
            appId: this.appId,
        }, {
            headers: constHeaders,
            responseType: 'json',
        })

        console.log(res)

        return 'OK'
    }

    @Get('personal/getProfile')
    async getProfile() {
        let appId = this.appId
        let target = `${gateway}/personal/getProfile`
        let res = await gewe.post(target, {
            appId,
        }, {
            headers: constHeaders,
            responseType: 'json',
        })


        if (res.status == 200 && res.data.ret) {
            let loginInfo = res.data.data
            let knex = knext(this)
            await knex.fromORM(WechatAppid).update({
                "uin": loginInfo.uin,
                "wxid": loginInfo.wxid,
                //"nickName": loginInfo.nickName,
                "mobile": loginInfo.mobile,
                "alias": loginInfo.alias
            }).where({ appId })
        }

        //console.log(res)

        return 'OK'
    }

    @Post('contacts/fetchContactsList')
    async fetchContactsList(@Req() request, @Body('appId') appId, @Response() resp: Res) {
        let target = `${gateway}/contacts/fetchContactsList`
        let res = await gewe.post(target, {
            appId: appId,
        }, {
            headers: constHeaders,
            responseType: 'json',
        })

        resp.set(res.headers)
            .status(res.status)
            .json(res.data)
            .end()
    }

    @Post('contacts/getBriefInfo')
    async getBriefInfo(@Body('wxids') wxids, @Body('appId') appId, @Response() resp: Res) {

        let loadedInfos = (wxids && wxids.length > 0) ? await this.redisService.redis().hmGet(`CONTACT_INFOS`, wxids) : [];

        let notLoadWxids = wxids.filter((wxid, index) => {
            return !loadedInfos[index]
        })

        loadedInfos = loadedInfos.filter((info) => !!info)

        loadedInfos = loadedInfos.map((info) => JSON.parse(info))

        if (notLoadWxids.length > 0) {
            let target = `${gateway}/contacts/getBriefInfo`
            let res = await gewe.post(target, {
                appId: appId,
                wxids: notLoadWxids
            }, {
                headers: constHeaders,
                responseType: 'json',
            })

            if (res.data.data) {
                notLoadWxids = res.data.data

                let multi = this.redisService.redis().multi()

                for (const info of res.data.data) {
                    multi.hSet(`CONTACT_INFOS`, info.userName, JSON.stringify(info));
                }

                await multi.exec()
            } else {
                notLoadWxids = []
            }
        }

        let result = loadedInfos.concat(notLoadWxids)

        resp.json({
            "ret": 200,
            "msg": "获取联系人信息成功",
            "data": result
        })
            .end()
    }

    @Post('message/postText')
    async postText(@Body() body, @Response() resp: Res) {
        let target = `${gateway}/message/postText`
        let res = await gewe.post(target, {
            appId: this.appId,
            ...body
        }, {
            headers: constHeaders,
            responseType: 'json',
        })

        resp.set(res.headers)
            .status(res.status)
            .json(res.data)
            .end()
    }

    //此接口用于,手机设备在线但IPad不在线,则可以调用该接口直接拉起手机设备登录弹窗,确认登录。
    //前提是手机设备在线,手机点击退出登录、新设备登录次日、官方风控下线 都无效。
    @Get('login/dialogLogin')
    async dialogLogin() {
        let target = `${gateway}/login/dialogLogin`
        let res = await gewe.post(target, {
            appId: this.appId,
            regionId: '460000'

        }, {
            headers: constHeaders,
            responseType: 'json',
        })


        // msg:
        // '账户已达登录上限'
        // ret:
        // 500

        console.log(res)

        return 'OK'
    }

    @Get('sql/validate')
    async sqlValidate() {
        let knex = knext(this)
        await knex.fromORM(WechatAppid).insert({
            appId: this.appId,
            uuid: this.uuid,
        })
    }

    @Get('*/*')
    async proxyGet(@Req() reqeust, @Headers() headers, @Body() body, @Response() resp: Res) {


        return 'OK'
    }

    @Post('*/*')
    async proxy(@Req() reqeust, @Headers() _headers, @Body() body, @Response() resp: Res) {

        let comps = reqeust.url.split('/')
        let mod = comps[comps.length - 2]
        let method = comps[comps.length - 1]
        let target = `${gateway}/${mod}/${method}`
        let data = {}
        for (const key in body) {
            data[key] = body[key]
        }

        try {
            let res = await gewe.post(target, body, {
                headers: {
                    ...constHeaders,
                    ..._headers
                },
                responseType: 'json',
            })

            resp.set(res.headers)
                .status(res.status)
                .json(res.data)
                .end()

        } catch (e) {
            return 'FLASE'
        }
    }
}